# -*- coding: utf-8 -*-
# 各种信号和槽函数
from PyQt5.QtWidgets import QMainWindow
from ui.ui_mainview import Ui_MainWindow
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QTimer
from .imgproc import Imgproc

class WorkerThread(QThread):
    """通用工作线程类，用于执行耗时操作"""
    # 定义信号
    finished = pyqtSignal()  # 任务完成信号
    error = pyqtSignal(str)  # 错误信号
    progress = pyqtSignal(int)  # 进度信号
    result = pyqtSignal(object)  # 结果信号
    camera_started = pyqtSignal()  # 摄像头启动成功信号
    camera_failed = pyqtSignal(str)  # 摄像头启动失败信号
    continuous_detection_started = pyqtSignal()  # 连续检测启动信号
    continuous_detection_stopped = pyqtSignal()  # 连续检测停止信号

    def __init__(self, task_function=None, *args, **kwargs):
        """
        初始化工作线程
        :param task_function: 要执行的任务函数
        :param args: 传递给任务函数的位置参数
        :param kwargs: 传递给任务函数的关键字参数
        """
        super().__init__()
        self.task_function = task_function
        self.args = args
        self.kwargs = kwargs
        self.is_running = True
        self.camera_manager = None
        self.continuous_detection_active = False
        self.continuous_timer = None
        self.imgproc = None

    def run(self):
        """执行线程的主要方法"""
        try:
            if self.task_function:
                result = self.task_function(*self.args, **self.kwargs)
                if result is not None:
                    self.result.emit(result)
            self.finished.emit()
        except Exception as e:
            self.error.emit(str(e))

    def stop(self):
        """停止线程"""
        self.is_running = False
        self.stop_continuous_detection()
        if self.camera_manager:
            self.camera_manager.stop_camera()
        self.wait()
    
    def start_integrated_camera(self, graphics_view, status_callback=None, camera_index=-1):
        """启动内置摄像头的线程方法"""
        try:
            from .device import CameraManager
            
            # 创建相机管理器
            self.camera_manager = CameraManager(graphics_view)
            
            # 启动内置摄像头
            if self.camera_manager.start_integrated_camera(status_callback, camera_index):
                self.camera_started.emit()
                return True
            else:
                self.camera_failed.emit("无法启动内置摄像头")
                return False
        except Exception as e:
            self.camera_failed.emit(f"启动摄像头时出错: {e}")
            return False
    
    def start_usb_camera(self, graphics_view, status_callback=None, camera_index=1):
        """启动USB摄像头的线程方法"""
        try:
            from .device import CameraManager
            
            # 创建相机管理器
            self.camera_manager = CameraManager(graphics_view)
            
            # 启动USB摄像头
            if self.camera_manager.start_usb_camera(camera_index, status_callback):
                self.camera_started.emit()
                return True
            else:
                self.camera_failed.emit(f"无法启动USB摄像头 {camera_index}")
                return False
        except Exception as e:
            self.camera_failed.emit(f"启动USB摄像头时出错: {e}")
            return False
    
    def start_continuous_detection(self, algorithm, result_graphics_view, status_callback=None, interval=100, imgproc=None, main_window=None):
        """
        启动连续特征点检测
        
        Args:
            algorithm: 特征检测算法名称
            result_graphics_view: 结果显示的图形视图
            status_callback: 状态更新回调函数
            interval: 检测间隔（毫秒）
            imgproc: 图像处理对象（可选，如果不提供则创建新的）
            main_window: 主窗口对象（用于获取标定系数）
        """
        try:
            if not self.camera_manager or not self.camera_manager.camera.is_connected:
                self.error.emit("摄像头未连接")
                return False
            
            # 使用提供的图像处理对象或创建新的
            if imgproc is not None:
                self.imgproc = imgproc
            else:
                self.imgproc = Imgproc()
            
            # 保存主窗口引用（用于获取标定系数）
            self.main_window = main_window
            
            # 重置连续检测状态
            self.imgproc.reset_continuous_detection()
            
            # 设置连续检测标志
            self.continuous_detection_active = True
            
            # 创建定时器进行连续检测
            self.continuous_timer = QTimer()
            self.continuous_timer.timeout.connect(
                lambda: self._perform_continuous_detection(algorithm, result_graphics_view, status_callback)
            )
            self.continuous_timer.start(interval)
            
            self.continuous_detection_started.emit()
            return True
            
        except Exception as e:
            self.error.emit(f"启动连续检测失败: {e}")
            return False
    
    def stop_continuous_detection(self):
        """停止连续特征点检测"""
        self.continuous_detection_active = False
        if self.continuous_timer:
            self.continuous_timer.stop()
            self.continuous_timer = None
        
        if self.imgproc:
            self.imgproc.reset_continuous_detection()
        
        self.continuous_detection_stopped.emit()
    
    def _perform_continuous_detection(self, algorithm, result_graphics_view, status_callback):
        """执行单次连续检测"""
        if not self.continuous_detection_active:
            return
        
        try:
            # 获取当前帧
            current_frame = self.camera_manager.camera.capture_frame()
            if current_frame is None:
                return
            
            # 获取标定系数（从主窗口的lineEdit_k获取）
            calibration_factor = None
            try:
                if hasattr(self, 'main_window') and self.main_window:
                    calibration_text = self.main_window.lineEdit_k.text()
                    if calibration_text and calibration_text.strip():
                        calibration_factor = float(calibration_text)
                        print(f"使用界面标定系数: {calibration_factor:.9f} 米/像素")
            except (ValueError, AttributeError) as e:
                print(f"获取标定系数失败: {e}")
            
            # 执行连续检测
            self.imgproc.detect_and_display_features_continuous(
                current_frame,
                algorithm,
                self.camera_manager,
                result_graphics_view,
                status_callback,
                calibration_factor
            )
            
        except Exception as e:
            if status_callback:
                status_callback(f"连续检测出错: {e}", 3000)


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.camera_thread = None
        self.continuous_detection_active = False
        self.imgproc = None  # 添加图像处理对象
        self.init_ui()
        self.load_calibration_on_startup()  # 启动时加载标定信息
    
    def init_ui(self):
        """初始化UI设置"""
        # 在这里添加UI初始化代码
        self.setup_connections()
    
    def setup_connections(self):
        """设置信号和槽的连接"""
        # 连接菜单动作点击事件
        self.actionintergrated_camera.triggered.connect(self.on_intergrated_camera_clicked)
        self.actionUSB.triggered.connect(self.on_usb_camera_clicked)
        self.actionImaging_zoom.triggered.connect(self.on_imaging_zoom_clicked)
        self.action.triggered.connect(self.on_line_structure_light_clicked)
        
        # 连接特征点按钮点击事件
        self.pushButton_key_point.clicked.connect(self.on_feature_point_clicked)
        
        # 连接标定比例尺按钮点击事件
        self.pushButton_calibrate.clicked.connect(self.on_calibrate_clicked)
        
        # 连接分辨率调整按钮点击事件
        self.pushButton_resolution.clicked.connect(self.on_resolution_adjust_clicked)

    def on_intergrated_camera_clicked(self):
        """集成相机按钮点击事件处理"""
        print("集成相机按钮被点击了！")
        
        # 显示相机选择对话框
        from .camera_dialog import CameraSelectionDialog
        selected_camera_index = CameraSelectionDialog.select_camera(self)
        
        if selected_camera_index == -1:
            # 用户取消了选择
            return
        
        # 创建并启动摄像头线程
        if self.camera_thread is None:
            self.camera_thread = WorkerThread()
            self.camera_thread.camera_started.connect(self.on_camera_started)
            self.camera_thread.camera_failed.connect(self.on_camera_failed)
            self.camera_thread.continuous_detection_started.connect(self.on_continuous_detection_started)
            self.camera_thread.continuous_detection_stopped.connect(self.on_continuous_detection_stopped)

        # 根据选择的相机类型启动相应的摄像头
        if selected_camera_index == -1:
            # 内置相机
            self.camera_thread.start_integrated_camera(self.graphicsView, self.on_update_statusbar, -1)
        else:
            # USB相机
            self.camera_thread.start_usb_camera(self.graphicsView, self.on_update_statusbar, selected_camera_index)
    
    def on_camera_started(self):
        """摄像头启动成功回调"""
        print("内置摄像头启动成功，画面将显示在graphicsView中")
        self.on_update_statusbar("摄像头已启动，正在初始化...", 2000)
    
    def on_camera_failed(self, error_message):
        """摄像头启动失败回调"""
        print(f"内置摄像头启动失败: {error_message}")
        self.on_update_statusbar(f"摄像头启动失败: {error_message}", 5000)
       
    def on_usb_camera_clicked(self):
        """USB相机按钮点击事件处理"""
        print("USB相机按钮被点击了！")
        
        # 显示相机选择对话框
        from .camera_dialog import CameraSelectionDialog
        selected_camera_index = CameraSelectionDialog.select_camera(self)
        
        if selected_camera_index == -1:
            # 用户取消了选择
            return
        
        # 创建并启动摄像头线程
        if self.camera_thread is None:
            self.camera_thread = WorkerThread()
            self.camera_thread.camera_started.connect(self.on_camera_started)
            self.camera_thread.camera_failed.connect(self.on_camera_failed)
            self.camera_thread.continuous_detection_started.connect(self.on_continuous_detection_started)
            self.camera_thread.continuous_detection_stopped.connect(self.on_continuous_detection_stopped)

        # 启动选中的相机
        if selected_camera_index == -1:
            # 内置相机
            self.camera_thread.start_integrated_camera(self.graphicsView, self.on_update_statusbar, -1)
        else:
            # USB相机
            self.camera_thread.start_usb_camera(self.graphicsView, self.on_update_statusbar, selected_camera_index)
        
    def on_imaging_zoom_clicked(self):
        """成像缩放按钮点击事件处理"""
        print("成像缩放按钮被点击了！")

    def on_totalstation_vision_guidance_clicked(self):
        """全站仪视觉引导按钮点击事件处理"""
        print("全站仪视觉引导按钮被点击了！")

    def on_line_structure_light_clicked(self):
        """线结构光按钮点击事件处理"""
        print("线结构光按钮被点击了！")
    
    def on_feature_point_clicked(self):
        """特征点按钮点击事件处理"""
        print("特征点按钮被点击了！")
        
        # 检查是否有摄像头在运行
        if (self.camera_thread is None or 
            self.camera_thread.camera_manager is None or 
            not self.camera_thread.camera_manager.camera.is_connected):
            self.on_update_statusbar("请先启动摄像头", 3000)
            return
        
        # 检查是否选择了连续模式
        if self.radioButton_continue.isChecked():
            # 连续模式
            if not self.continuous_detection_active:
                # 确保图像处理对象已创建
                if self.imgproc is None:
                    self.imgproc = Imgproc()
                
                # 启动连续检测
                algorithm = self.comboBox.currentText()
                print(f"启动连续特征点检测，算法: {algorithm}")
                
                if self.camera_thread.start_continuous_detection(
                    algorithm, 
                    self.graphicsView_result, 
                    self.on_update_statusbar,
                    interval=50,  # 20 FPS
                    imgproc=self.imgproc,  # 传递主窗口的图像处理对象
                    main_window=self  # 传递主窗口对象
                ):
                    self.continuous_detection_active = True
                    self.pushButton_key_point.setText("停止检测")
                else:
                    self.on_update_statusbar("启动连续检测失败", 3000)
            else:
                # 停止连续检测
                self.camera_thread.stop_continuous_detection()
                self.continuous_detection_active = False
                self.pushButton_key_point.setText("特征点")
                self.on_update_statusbar("连续检测已停止", 2000)
        else:
            # 单次检测模式
            # 获取当前选择的特征检测算法
            current_algorithm = self.comboBox.currentText()
            
            # 使用或创建图像处理对象
            if self.imgproc is None:
                self.imgproc = Imgproc()
            
            # 获取当前帧
            current_frame = self.camera_thread.camera_manager.camera.capture_frame()
            if current_frame is None:
                self.on_update_statusbar("无法获取当前帧", 3000)
                return
            
            # 检测特征点
            self.imgproc.detect_and_display_features(
                current_frame, 
                current_algorithm, 
                self.camera_thread.camera_manager, 
                self.graphicsView_result,
                self.on_update_statusbar
            )
    
    def on_continuous_detection_started(self):
        """连续检测启动回调"""
        print("连续特征点检测已启动")
        self.on_update_statusbar("连续特征点检测已启动", 2000)
    
    def on_continuous_detection_stopped(self):
        """连续检测停止回调"""
        print("连续特征点检测已停止")
        self.on_update_statusbar("连续特征点检测已停止", 2000)
    
    def on_calibrate_clicked(self):
        """标定比例尺按钮点击事件处理"""
        print("标定比例尺按钮被点击了！")
        
        # 检查是否有摄像头在运行
        if (self.camera_thread is None or 
            self.camera_thread.camera_manager is None or 
            not self.camera_thread.camera_manager.camera.is_connected):
            self.on_update_statusbar("请先启动摄像头", 3000)
            return
        
        # 获取当前帧
        current_frame = self.camera_thread.camera_manager.camera.capture_frame()
        if current_frame is None:
            self.on_update_statusbar("无法获取当前帧", 3000)
            return
        
        # 创建并显示标定对话框
        from .calibration_dialog import CalibrationDialog
        calibration_dialog = CalibrationDialog(current_frame, self)
        calibration_dialog.calibration_completed.connect(self.on_calibration_completed)
        
        # 显示对话框
        if calibration_dialog.exec_() == CalibrationDialog.Accepted:
            # 用户确认了标定结果
            scale_factor = calibration_dialog.get_scale_factor()
            self.on_update_statusbar(f"标定完成，比例尺系数: {scale_factor:.9f} 米/像素", 5000)
        else:
            # 用户取消了标定
            self.on_update_statusbar("标定已取消", 2000)
    
    def on_resolution_adjust_clicked(self):
        """分辨率调整按钮点击事件处理"""
        print("分辨率调整按钮被点击了！")
        
        # 检查是否有摄像头在运行
        if (self.camera_thread is None or 
            self.camera_thread.camera_manager is None or 
            not self.camera_thread.camera_manager.camera.is_connected):
            self.on_update_statusbar("请先启动摄像头", 3000)
            return
        
        # 获取当前摄像头信息
        camera_info = self.camera_thread.camera_manager.camera.get_camera_info()
        if camera_info is None:
            self.on_update_statusbar("无法获取摄像头信息", 3000)
            return
        
        current_width = camera_info.get('width', 640)
        current_height = camera_info.get('height', 480)
        current_fps = int(camera_info.get('fps', 30))  # 确保fps是整数
        
        print(f"当前摄像头设置: {current_width}x{current_height}, {current_fps:.1f}fps")
        
        # 创建并显示分辨率设置对话框
        from .resolution_dialog import ResolutionDialog
        resolution_dialog = ResolutionDialog(
            self, 
            current_width=current_width, 
            current_height=current_height, 
            current_fps=current_fps
        )
        
        # 连接分辨率改变信号
        resolution_dialog.resolution_changed.connect(self.on_resolution_changed)
        
        # 显示对话框
        if resolution_dialog.exec_() == ResolutionDialog.Accepted:
            # 用户确认了分辨率设置
            width, height, fps = resolution_dialog.get_selected_settings()
            self.on_update_statusbar(f"分辨率设置完成: {width}x{height}, {fps}fps", 3000)
        else:
            # 用户取消了设置
            self.on_update_statusbar("分辨率设置已取消", 2000)
    
    def on_calibration_completed(self, scale_factor):
        """
        标定完成回调
        
        Args:
            scale_factor (float): 比例尺系数（米/像素）
        """
        try:
            # 更新比例尺系数显示
            self.lineEdit_k.setText(f"{scale_factor:.9f}")
            
            # 更新主窗口的图像处理对象的像素大小
            if self.imgproc:
                self.imgproc.set_pixel_size(scale_factor)
                print(f"已更新主窗口图像处理对象的像素大小: {scale_factor} 米/像素")
            
            # 更新线程中的图像处理对象的像素大小
            if (self.camera_thread and 
                self.camera_thread.imgproc):
                self.camera_thread.imgproc.set_pixel_size(scale_factor)
                print(f"已更新线程图像处理对象的像素大小: {scale_factor} 米/像素")
            
            # 更新状态栏
            self.on_update_statusbar(f"标定完成！比例尺系数: {scale_factor:.9f} 米/像素，已保存到文件", 5000)
            
        except Exception as e:
            self.on_update_statusbar(f"更新标定结果时出错: {str(e)}", 5000)
    
    def load_calibration_on_startup(self):
        """程序启动时加载标定信息"""
        try:
            from .calibration_dialog import CalibrationDialog
            
            # 从文件加载标定系数
            scale_factor = CalibrationDialog.load_calibration_from_file()
            
            if scale_factor is not None:
                # 更新界面显示
                self.lineEdit_k.setText(f"{scale_factor:.9f}")
                
                # 创建图像处理对象并设置标定系数
                if self.imgproc is None:
                    self.imgproc = Imgproc()
                self.imgproc.set_pixel_size(scale_factor)
                
                print(f"程序启动时已加载标定系数: {scale_factor:.9f} 米/像素")
                self.on_update_statusbar(f"已加载保存的标定系数: {scale_factor:.9f} 米/像素", 3000)
            else:
                print("未找到保存的标定信息，使用默认值")
                self.on_update_statusbar("未找到保存的标定信息，使用默认值", 3000)
                
        except Exception as e:
            print(f"加载标定信息失败: {e}")
            self.on_update_statusbar("加载标定信息失败", 3000)

    def on_update_statusbar(self, message, timeout=5000):
        """
        通用状态栏更新函数
        
        Args:
            message (str): 要显示的消息
            timeout (int): 消息显示时间（毫秒），默认5秒，0表示永久显示
        """
        if hasattr(self, 'statusBar'):
            self.statusBar.showMessage(message, timeout)
            print(f"状态栏更新: {message}")
        else:
            print(f"状态栏不可用，消息: {message}")
    
    def update_statusbar_with_progress(self, message, progress_value=None, progress_max=None):
        """
        带进度条的状态栏更新函数
        
        Args:
            message (str): 要显示的消息
            progress_value (int): 当前进度值
            progress_max (int): 最大进度值
        """
        if hasattr(self, 'statusBar'):
            if progress_value is not None and progress_max is not None:
                progress_text = f" - 进度: {progress_value}/{progress_max}"
                full_message = f"{message}{progress_text}"
            else:
                full_message = message
            
            self.statusBar.showMessage(full_message)
            print(f"状态栏更新(带进度): {full_message}")
        else:
            print(f"状态栏不可用，消息: {message}")
    
    def clear_statusbar(self):
        """清除状态栏消息"""
        if hasattr(self, 'statusBar'):
            self.statusBar.clearMessage()
            print("状态栏已清除")
        else:
            print("状态栏不可用")
    
    def resizeEvent(self, event):
        """窗口大小改变事件"""
        super().resizeEvent(event)
        if self.camera_thread and self.camera_thread.camera_manager:
            self.camera_thread.camera_manager.resize_event()
        
        # 调整结果显示视图大小
        if hasattr(self, 'graphicsView_result') and self.graphicsView_result.scene():
            from PyQt5.QtCore import Qt
            self.graphicsView_result.fitInView(self.graphicsView_result.scene().sceneRect(), Qt.KeepAspectRatio)
    
    def closeEvent(self, event):
        """窗口关闭事件"""
        if self.camera_thread:
            self.camera_thread.stop()
        super().closeEvent(event)

    def on_resolution_changed(self, width, height, fps):
        """
        分辨率改变回调，保持视场不变
        
        Args:
            width (int): 新的宽度
            height (int): 新的高度
            fps (int): 新的帧率
        """
        try:
            if (self.camera_thread is None or 
                self.camera_thread.camera_manager is None or 
                not self.camera_thread.camera_manager.camera.is_connected):
                self.on_update_statusbar("摄像头未连接，无法调整分辨率", 3000)
                return
            
            # 使用新的方法应用分辨率改变，保持视场不变
            success = self.camera_thread.camera_manager.apply_resolution_change(width, height, fps)
            
            if success:
                # 获取实际设置的值
                actual_info = self.camera_thread.camera_manager.camera.get_camera_info()
                if actual_info:
                    actual_width = actual_info.get('width', width)
                    actual_height = actual_info.get('height', height)
                    actual_fps = actual_info.get('fps', fps)
                    
                    # 更新图像处理对象的帧率
                    if self.imgproc:
                        self.imgproc.set_frame_rate(actual_fps)
                        print(f"已更新图像处理对象帧率: {actual_fps:.1f} 帧/秒")
                    
                    # 更新线程中的图像处理对象的帧率
                    if (self.camera_thread and 
                        self.camera_thread.imgproc):
                        self.camera_thread.imgproc.set_frame_rate(actual_fps)
                        print(f"已更新线程图像处理对象帧率: {actual_fps:.1f} 帧/秒")
                    
                    # 检查设置是否完全匹配
                    if (actual_width == width and actual_height == height and 
                        abs(actual_fps - fps) < 5):
                        self.on_update_statusbar(f"分辨率设置成功，视场保持不变: {actual_width}x{actual_height}, {actual_fps:.1f}fps", 5000)
                    else:
                        self.on_update_statusbar(f"分辨率设置部分成功，视场保持不变: {actual_width}x{actual_height}, {actual_fps:.1f}fps", 5000)
                    
                    # 显示性能统计
                    self.show_performance_stats()
                    
                else:
                    self.on_update_statusbar("分辨率设置成功，但无法获取实际设置信息", 3000)
            else:
                self.on_update_statusbar(f"分辨率设置失败: {width}x{height} @ {fps}fps", 5000)
                
        except Exception as e:
            self.on_update_statusbar(f"分辨率调整出错: {str(e)}", 5000)
    
    def show_performance_stats(self):
        """显示性能统计信息"""
        try:
            if (self.camera_thread and 
                self.camera_thread.camera_manager):
                
                stats = self.camera_thread.camera_manager.get_performance_stats()
                
                # 获取摄像头信息
                camera_info = self.camera_thread.camera_manager.camera.get_camera_info()
                if camera_info:
                    resolution = f"{camera_info['width']}x{camera_info['height']}"
                    actual_fps = camera_info['fps']
                    
                    # 更新状态栏显示性能信息
                    performance_text = (f"摄像头运行中 | 分辨率: {resolution} | "
                                      f"实际FPS: {actual_fps:.1f} | "
                                      f"处理帧数: {stats['frame_count']}")
                    
                    self.on_update_statusbar(performance_text, 0)  # 0表示永久显示
                    
        except Exception as e:
            print(f"显示性能统计时出错: {e}")

    def on_roi_clicked(self):
        """ROI按钮点击事件处理"""
        print("ROI按钮被点击了！")
        # 这里添加你的ROI处理逻辑